home *** CD-ROM | disk | FTP | other *** search
- /*
- cl.cpp -- Container Lite v 1.82
- (C) Copyright 1993 John Webster Small
- All rights reserved
- */
-
- #include <string.h>
- #include <fstream.h>
- #include "cl.hpp"
-
-
- char memberStreamDelimiter = '\n';
-
- void cl::init(unsigned flags, unsigned maxNodes,
- unsigned limit, unsigned delta)
- {
- curNode = first = nodes = 0U;
- cmP = voidCmP0;
-
- /*
- The following relationships are maintained
- during operation of a cl:
-
- 1 <= delta <= lowLimit <= limit <= maxNodes
- <= CL_MAXNODES
- lowThreshold = lowLimit - delta;
- */
-
- if (maxNodes > CL_MAXNODES)
- maxNodes = CL_MAXNODES;
- if (limit > maxNodes)
- limit = maxNodes;
- if (delta > limit)
- delta = limit;
- if (!delta) {
- delta = 1;
- if (limit < delta)
- limit = delta;
- if (maxNodes < limit)
- maxNodes = limit;
- }
- linkS = (void **)0;
- this->limit = limit;
- this->delta = delta;
- this->maxNodes = maxNodes;
- lowLimit = limit;
- lowThreshold = lowLimit - delta;
- this->flags = (flags | CL_SORTED);
- }
-
- void cl::assign(const cl& b)
- {
- if (flags & CL_DDELETE)
- allDel();
- else
- allRmv();
- setDelta(1); setLimit(1); setMaxNodes(1);
- setMaxNodes(b.MaxNodes());
- setLimit(b.Limit());
- setDelta(b.Delta());
- resetFlags(CL_ALL_FLAGS);
- setFlags(b.Flags());
- setFlags(CL_DNEW | CL_DDELETE);
- setCmP(b.CmP());
- for (unsigned i = 0U; i < b.Nodes(); i++)
- insQNew(b.atGet(i));
- setCurNode(b.CurNode());
- }
-
- void cl::destruct()
- {
- if (flags & CL_DDELETE)
- allDel();
- else
- allRmv();
- if (linkS) {
- delete linkS;
- linkS = (void **)0;
- }
- }
-
- int cl::put(ostream& os)
- {
- if (!(os << maxNodes << endm << limit << endm
- << delta << endm << nodes << endm
- << curNode << endm << flags << endm
- << cmP2ID(cmP) << endm))
- return 0;
- for (unsigned i = 0U; i < nodes; i++)
- if (!Dput(os,atGet(i)))
- return 0;
- return 1;
- }
-
- int cl::get(istream& is)
- {
- unsigned maxNodes, limit, delta, nodes;
- unsigned curNode, flags, cmPid;
-
- if (!(is >> maxNodes >> nextm >> limit >> nextm
- >> delta >> nextm >> nodes >> nextm
- >> curNode >> nextm >> flags >> nextm
- >> cmPid >> nextm))
- return 0;
- flags |= CL_DDELETE;
- //reloaded nodes are dynamic!
- setMaxNodes(maxNodes);
- setLimit(limit);
- setDelta(delta);
- setFlags(flags);
- setCmP(ID2cmP(cmPid));
- void * D;
- for (unsigned i = 0U; i < nodes; i++)
- if (!insQ(D=Dget(is)))
- if (D) {
- Ddelete(D);
- return 0;
- }
- setCurNode(curNode);
- return 1;
- }
-
- int cl::load(const char * filename)
- {
- int ok = 0;
- allClr();
- if (filename) {
- ifstream is(filename);
- if (is) {
- ok = get(is);
- is.close();
- }
- }
- return ok;
- }
-
- int cl::save(const char * filename)
- {
- int ok = 0;
- if (Flags(CL_DSTORE)) {
- ofstream os(filename);
- if (os) {
- ok = put(os);
- os.close();
- }
- }
- return ok;
- }
-
- void cl::vforEach(voidApplY B, va_list args)
- {
- if (!linkS || !B || !nodes)
- return;
- for (unsigned i = 0U; i < nodes; i++)
- (*B)(linkS[(first+i)%limit],args);
- }
-
- cl::cl(void ** argv, unsigned argc,
- unsigned flags)
- {
- init(flags,CL_MAXNODES,argc,CL_DELTA);
- if (maxNodes)
- if (argv)
- if (argc > 0U)
- while (argc--)
- (void) push(argv[argc]);
- else
- for (argc = 0U;
- insQ(argv[argc]);
- argc++)
- /* null stmt */;
- }
-
- int cl::operator==(const cl& b) const
- {
- if (!cmP) return 0;
- for (unsigned i = 0; i < nodes; i++) {
- if (i >= b.Nodes())
- return 0;
- if ((*cmP)(atGet(i),b.atGet(i)))
- return 0;
- }
- if (i < b.Nodes())
- return 0;
- return 1;
- }
-
- int cl::operator>(const cl& b) const
- {
- if (!cmP) return 0;
- unsigned c;
- for (unsigned i = 0; i < nodes; i++) {
- if (i >= b.Nodes())
- return 1;
- if ((c = (*cmP)(atGet(i),b.atGet(i)))
- != 0)
- return (c > 0);
- }
- if (i < b.Nodes())
- return -1;
- return 0;
- }
-
- void ** cl::vector(void ** argv, unsigned argc) const
- {
- void ** V;
-
- if ((V = argv) == (void **)0) {
- if (!nodes)
- return (void **)0;
- if ((V = new void *[argc=nodes+1])
- == (void **)0)
- return (void **)0;
- }
- else if (argc) if (nodes > argc)
- return (void **)0;
- for (unsigned i = 0U; i < nodes; i++)
- V[i] = atGet(i);
- while (i < argc)
- V[i++] = (void *)0;
- return V;
- }
-
- unsigned cl::setLimit(unsigned newLimit)
- {
- void ** newLinkS;
- unsigned headNodes;
-
- if (newLimit < nodes)
- newLimit = nodes;
- else if (newLimit > maxNodes)
- newLimit = maxNodes;
- if (newLimit < delta)
- newLimit = delta;
- if (!newLimit || newLimit == limit)
- return 0U;
- if (!linkS)
- return (limit = newLimit);
- if ((newLinkS = new void *[newLimit])
- == (void **)0)
- return 0U;
- if ((headNodes = limit - first) > nodes)
- headNodes = nodes;
- if (headNodes) // move leading nodes
- memcpy(newLinkS,&linkS[first],
- sizeof(linkS[0U])*headNodes);
- /* copy wrap around trailing nodes */
- if (headNodes < nodes)
- memcpy(&newLinkS[headNodes],linkS,
- sizeof(linkS[0U])*
- (nodes-headNodes));
- if (newLimit > limit)
- if (newLimit - delta > limit)
- lowLimit = newLimit - delta;
- else
- lowLimit = limit;
- else
- if (newLimit - delta > delta)
- lowLimit = newLimit - delta;
- else
- lowLimit = delta;
- lowThreshold = lowLimit - delta;
- delete linkS;
- linkS = newLinkS;
- limit = newLimit;
- first = 0U;
- return limit;
- }
-
- unsigned cl::setDelta(unsigned newDelta)
- {
- return ((newDelta && newDelta <= lowLimit)?
- delta = newDelta : 0U);
- }
-
- unsigned cl::setMaxNodes(unsigned newMaxNodes)
- {
- return ((newMaxNodes >= limit)?
- (maxNodes = (newMaxNodes
- > CL_MAXNODES)? CL_MAXNODES
- : newMaxNodes) : 0U);
- }
-
- void * cl::atIns(unsigned n, void * D)
- {
- void ** newLinkS;
- unsigned newLimit, i;
-
- if (!D)
- return (void *)0;
- if (nodes == limit) { // no vacancy - expand
- if (limit == maxNodes)
- return (void *)0;
- newLimit = (maxNodes - delta > limit)?
- limit + delta : maxNodes;
- if ((newLinkS = new void *[newLimit])
- == (void **)0) //expansion unavailable
- return (void *)0;
- if (!Dattach(D)) {// data refuses binding
- delete newLinkS;
- return (void *)0;
- }
- newLinkS[((n <= nodes)? n : n = nodes)] = D;
- // calc headNodes
- if (n <= (i = limit - first)) {
- // insert in head section
- if (n) {// postfix or split head
- memcpy(newLinkS,&linkS[first],
- sizeof(linkS[0U])*n);
- if (n < i) // it's a split
- memcpy(&newLinkS[n+1],
- &linkS[first+n],
- sizeof(linkS[0U])*(i-n));
- }
- else // prefix head
- memcpy(&newLinkS[1],&linkS[first],
- sizeof(linkS[0U])*i);
- if (i < nodes) // copy tail
- memcpy(&newLinkS[1+i],linkS,
- sizeof(linkS[0U])
- *(nodes-i));
- }
- else { // insert in tail section
- // copy head first
- memcpy(newLinkS,&linkS[first],
- sizeof(linkS[0U])*i);
- if (i < nodes) { // copy tail
- memcpy(&newLinkS[i],linkS,
- sizeof(linkS[0U])*(n-i));
- if (n < nodes) // it's a tail split
- memcpy(&newLinkS[n+1],
- &linkS[n-i],
- sizeof(linkS[0U])
- *(nodes-n));
- }
- }
- // Compute next smaller linkS size
- // and threshold for shrinking.
- lowLimit = limit;
- lowThreshold = lowLimit - delta;
- // swap new for old
- delete linkS;
- linkS = newLinkS;
- limit = newLimit;
- first = 0U;
- }
- else { // vacancy
- if (!linkS)
- if ((linkS = new void *[limit])
- == (void **)0)
- return (void *)0;
- if (!Dattach(D)) {
- if (!nodes) {
- delete linkS;
- linkS = (void **)0;
- }
- return (void *)0;
- }
- if (!n) // push
- linkS[first? --first
- : (first = limit - 1)] = D;
- else if (n >= nodes) // insQ
- linkS[(first+(n=nodes))%limit] = D;
- else { // insert interior
- i = (first + n) % limit;
- if (i < first || !first)
- // move rear rightward
- memmove(&linkS[i+1],&linkS[i],
- sizeof(linkS[0U])
- * (nodes-n));
- else { // move front leftward
- memmove(&linkS[first-1],
- &linkS[first],
- sizeof(linkS[0U])
- *(n));
- first--;
- i--;
- }
- linkS[i] = D;
- }
- }
- nodes++;
- if (n <= curNode)
- curNode++;
- flags &= ~CL_SORTED;
- return D;
- }
-
-
- void * cl::atInsNew(unsigned n, const void * D)
- {
- void * cD;
-
- if (D && flags & CL_DNEW)
- if ((cD = Dnew(D)) != (void *)0)
- if (atIns(n,cD)) {
- flags |= CL_DNEWED;
- return cD;
- }
- else
- Ddelete(cD);
- return (void *)0;
- }
-
- void * cl::atRmv(unsigned n)
- {
- void ** newLinkS = (void **)0;
- unsigned newLimit, i;
- void * D;
-
- if (!linkS || n >= nodes)
- return (void *)0;
- D = linkS[(((i=first+n) >=limit)? i-=limit:i)];
- if (nodes <= lowThreshold) {
- // get ready to contract
- newLimit = lowLimit;
- newLinkS = new void *[newLimit];
- // Compute next smaller linkS
- // size and threshold for
- // shrinking.
- if (nodes < delta)
- lowThreshold = 0;
- else
- lowThreshold -= delta;
- lowLimit = lowThreshold + delta;
- }
- if (newLinkS) { // remove and contract
- // calc head nodes
- if ((i = limit - first) > nodes)
- i = nodes;
- if (n < i) {
- // rmv from head section
- if (n) { // rmv from head
- memcpy(newLinkS,&linkS[first],
- sizeof(linkS[0U])*n);
- if (n < i - 1)
- memcpy(&newLinkS[n],
- &linkS[first+n+1],
- sizeof(linkS[0U])*(i-n-1));
- }
- else // pop head
- memcpy(newLinkS,&linkS[first+1],
- sizeof(linkS[0U])*(i-1));
- if (i < nodes) // copy tail
- memcpy(&newLinkS[i-1],linkS,
- sizeof(linkS[0U])
- *(nodes-i));
- }
- else { // i <= n < nodes
- // rmv from tail section
- // copy head first
- memcpy(newLinkS,&linkS[first],
- sizeof(linkS[0U])*i);
- if (i == n) { // pop tail
- if (n < nodes - 1)
- // copy trailing tail
- memcpy(&newLinkS[i],&linkS[1],
- sizeof(linkS[0U])*(nodes-n-1));
- }
- else { // copy up to n in tail
- memcpy(&newLinkS[i],linkS,
- sizeof(linkS[0U])*(n-i));
- // skip n'th node
- if (n < nodes - 1)
- // copy anything trailing n'th node
- memcpy(&newLinkS[n],linkS[n-i+1],
- sizeof(linkS[0U])*(nodes-n-1));
- }
- }
- // swap new for old
- delete linkS;
- linkS = newLinkS;
- limit = newLimit;
- first = 0U;
- }
- else { // simply remove
- if (!n) { // pop
- if (++first >= limit)
- first = 0U;
- }
- else if (n != nodes-1) // del interior
- if (i < first) // move tail leftward
- memmove(&linkS[i],&linkS[i+1],
- sizeof(linkS[0U])
- *(nodes-n-1));
- else { // move head rightward
- memmove(&linkS[first+1],
- &linkS[first],
- sizeof(linkS[0U])*n);
- first++;
- }
- }
- if (n < curNode)
- curNode--;
- else if (n == curNode)
- curNode = nodes-1;
- if (--nodes == 0U) {
- flags |= CL_SORTED;
- delete linkS;
- linkS = (void **)0;
- }
- Ddetach(D);
- return D;
- }
-
- void cl::allRmv()
- {
- flags &= ~CL_DNEWED;
- while (atRmv(0U)) /* null stmt */ ;
- }
-
- int cl::atDel(unsigned n)
- {
- void * D;
-
- if (flags & CL_DDELETE)
- if ((D = atRmv(n)) != (void *)0) {
- Ddelete(D);
- return 1;
- }
- return 0;
- }
-
- void * cl::atDelAsg(unsigned n, void * D)
- {
- void * S;
-
- if (D && flags & CL_DASSIGN
- && flags & CL_DDELETE)
- if ((S = atGet(n)) != (void *)0)
- if (D != S) {
- (flags &= ~CL_DREAD)
- |= CL_DREAD_DEL;
- if (Dassign(D,S)) {
- (void) atDel(n);
- return D;
- }
- }
- return (void *)0;
- }
-
- int cl::allDel()
- {
- void * D;
-
- if (flags & CL_DDELETE) {
- while ((D = atRmv(0U)) != (void *)0)
- Ddelete(D);
- return 1;
- }
- return 0;
- }
-
- void cl::allClr()
- {
- if (flags & CL_DDELETE)
- allDel();
- else
- allRmv();
- }
-
- void * cl::atPut(unsigned n, void * D)
- {
- if (linkS && D && (n < nodes)) {
- void *& N = linkS[(first+n)%limit];
- if (D != N) if (Dattach(D)) {
- flags &= ~CL_SORTED;
- Ddetach(N);
- if (flags & CL_DDELETE)
- Ddelete(N);
- return (N=D);
- }
- }
- return (void *)0;
- }
-
- void * cl::atPutNew(unsigned n, const void * D)
- {
- void * oldD, * cD;
-
- if (!D || !(flags & CL_DNEW))
- return (void *)0;
- if ((oldD = atGet(n)) == (void *)0)
- return (void *)0;
- if (oldD == D)
- return (void *)0;
- if ((cD = Dnew(D)) != (void *)0)
- if (atPut(n,cD)) {
- flags |= CL_DNEWED;
- return cD;
- }
- else
- Ddelete(cD);
- return (void *)0;
- }
-
- void * cl::atPutAsg(unsigned n, const void * D)
- {
- void * oldD;
-
- if (D && flags & CL_DASSIGN)
- if ((oldD = atGet(n)) != (void *)0)
- if (D != oldD) {
- flags &= ~(CL_DREAD
- | CL_DREAD_DEL);
- return Dassign(oldD,D);
- }
- return (void *)0;
- }
-
- void * cl::atGet(unsigned n) const
- {
- return ((linkS && (n < nodes))?
- linkS[(first+n)%limit] : (void *)0);
- }
-
- void * cl::atGetAsg(unsigned n, void * D)
- {
- void * N;
-
- if (D && flags & CL_DASSIGN)
- if ((N = atGet(n)) != (void *)0)
- if (D != N) {
- (flags &= ~CL_DREAD_DEL)
- |= CL_DREAD;
- return Dassign(D,N);
- }
- return (void *)0;
- }
-
- void * cl::atXchg(unsigned n, void * D)
- {
- if (linkS && D && (n < nodes))
- if (Dattach(D)) {
- flags &= ~CL_SORTED;
- void *& N = linkS[(first+n)
- %limit];
- void * oldD = N;
- N = D;
- Ddetach(oldD);
- return oldD;
- }
- return (void *)0;
- }
-
- unsigned cl::index(const void * D) const
- {
- unsigned i;
-
- if (linkS && D)
- for (i = 0U; i < nodes; i++)
- if (D == linkS[(first+i)
- %limit])
- return i;
- return CL_NOTFOUND;
- }
-
- unsigned cl::CurNode() const
- {
- return ((curNode < nodes)?
- curNode : CL_NOTFOUND);
- }
-
- int cl::setCurNode(unsigned n)
- {
- return ((curNode = ((n > nodes)? nodes : n))
- < nodes);
- }
-
- void * cl::ins(void * D)
- {
- if (atIns(curNode+1,D)) {
- if (++curNode >= nodes)
- curNode = nodes - 1;
- return D;
- }
- return (void *)0;
- }
-
- void * cl::insNew(const void * D)
- {
- void * cD;
-
- if (D && flags & CL_DNEW)
- if ((cD = Dnew(D)) != (void *)0)
- if (ins(cD)) {
- flags |= CL_DNEWED;
- return cD;
- }
- else
- Ddelete(cD);
- return (void *)0;
- }
-
- void * cl::rmv()
- {
- void * D;
- unsigned n;
-
- if ((D = atRmv(n=curNode)) != (void *)0)
- if (n)
- curNode = n - 1;
- else
- curNode = 0;
- return D;
- }
-
- int cl::del()
- {
- void * D;
-
- if (flags & CL_DDELETE)
- if ((D = rmv()) != (void *)0) {
- Ddelete(D);
- return 1;
- }
- return 0;
- }
-
- void * cl::delAsg(void * D)
- {
- void * S;
-
- if (D && flags & CL_DASSIGN
- && flags & CL_DDELETE)
- if ((S = atGet(curNode)) != (void *)0)
- if (D != S) {
- (flags &= ~CL_DREAD)
- |= CL_DREAD_DEL;
- if (Dassign(D,S)) {
- (void) del();
- return D;
- }
- }
- return (void *)0;
- }
-
- void * cl::next()
- {
- if (linkS) {
- if (curNode >= nodes)
- curNode = 0U;
- else
- curNode++;
- if (curNode < nodes)
- return linkS[(first+curNode)
- %limit];
- }
- return (void *)0;
- }
-
- void * cl::nextAsg(void * D)
- {
- unsigned oldCurNode = curNode;
- void * S;
-
- if (D && flags & CL_DASSIGN)
- if ((S = next()) != (void *)0) {
- if (D != S) {
- (flags &= ~CL_DREAD_DEL)
- |= CL_DREAD;
- if (Dassign(D,S))
- return D;
- }
- curNode = oldCurNode;
- }
- return (void *)0;
- }
-
- void * cl::prev()
- {
- if (linkS) {
- if (curNode) {
- if (curNode > nodes)
- curNode = nodes;
- curNode--;
- }
- else
- curNode = nodes;
- if (curNode < nodes)
- return linkS[(first+curNode)
- %limit];
- }
- return (void *)0;
- }
-
- void * cl::prevAsg(void * D)
- {
- unsigned oldCurNode = curNode;
- void * S;
-
- if (D && flags & CL_DASSIGN)
- if ((S = prev()) != (void *)0) {
- if (D != S) {
- (flags &= ~CL_DREAD_DEL)
- |= CL_DREAD;
- if (Dassign(D,S))
- return D;
- }
- curNode = oldCurNode;
- }
- return (void *)0;
- }
-
- int cl::sort(voidCmP cmP)
- {
- unsigned low, mid, high;
- unsigned d;
- void * D;
-
- /*
- The current node is always reset to undefined
- regardless of the outcome of sort.
- */
-
- curNode = nodes;
- if (!this->cmP)
- this->cmP = DcmP(voidCmP0);
- if (flags & CL_SORTED) {
- if (this->cmP == cmP || !cmP)
- return 1;
- }
- else if (!this->cmP && !cmP)
- return 0;
- if (cmP) {
- this->cmP = cmP;
- flags &= ~CL_SORTED;
- }
- if (!nodes || !linkS)
- return (int) (flags |= CL_SORTED);
- if (first) {
- /* form contiguous block at front */
- d = (first + nodes) % limit;
- if (d > first)
- memmove(linkS,&linkS[first],
- sizeof(linkS[0U])*nodes);
- else if (d < first)
- memmove(&linkS[d],
- &linkS[first],
- sizeof(linkS[0U])
- *(limit-first));
- /* else array is full/contiguous */
- first = 0U;
- }
- for (high = d = 1; d < nodes; high = ++d) {
- low = 0U;
- D = linkS[d];
- while (low < high) {
- mid = low +
- ((high - low) >> 1);
- if ((*this->cmP)(D,
- linkS[mid]) <= 0)
- high = mid;
- else
- low = mid + 1;
- }
- if (high < d) {
- memmove(&linkS[high+1],
- &linkS[high],
- sizeof(linkS[0U])
- *(d-high));
- linkS[high] = D;
- }
- }
- return (int) (flags |= CL_SORTED);
- }
-
- void * cl::insSort(void * D)
- {
- unsigned low, mid, high;
- void * ok;
-
- /*
- The current node is left undefined if
- anything fails, otherwise it is set to the
- newly inserted node.
- */
-
- curNode = nodes;
- if (!cmP) if ((cmP = DcmP(voidCmP0))
- == voidCmP0) return (void *)0;
- if (!D || nodes >= maxNodes)
- return (void *)0;
- if (!linkS)
- if ((linkS = new void *[limit])
- == (void **)0)
- return (void *)0;
- if (!(flags & CL_SORTED))
- if (!sort())
- return (void *)0;
- low = 0U;
- high = nodes;
- while (low < high) {
- mid = low + ((high - low) >> 1);
- if ((*cmP)(D,
- linkS[(first+mid)%limit]) <= 0)
- high = mid;
- else
- low = mid + 1;
- }
- if ((ok = atIns(high,D)) != (void *)0)
- curNode = high;
- /* atIns() resets sorted to zero */
- flags |= CL_SORTED;
- return ok;
- }
-
- void * cl::insSortNew(const void * D)
- {
- void * cD;
-
- if (D && flags & CL_DNEW)
- if ((cD = Dnew(D)) != (void *)0)
- if (insSort(cD)) {
- flags |= CL_DNEWED;
- return cD;
- }
- else
- Ddelete(cD);
- return (void *)0;
- }
-
- void * cl::insUnique(void * D)
- {
- if (!findFirst(D))
- return insSort(D);
- return (void *)0;
- }
-
- void * cl::insUniqueNew(const void * D)
- {
- if (!findFirst(D))
- return insSortNew(D);
- return (void *)0;
- }
-
- void * cl::findFirst(const void * K)
- {
- unsigned low, mid, high;
- void * D;
-
- /*
- The current node is left undefined if
- anything fails, otherwise it is set to the
- newly found node.
- */
-
- curNode = nodes;
- if (!cmP) if ((cmP = DcmP(voidCmP0))
- == voidCmP0) return (void *) 0;
- if (!linkS || !K || !nodes)
- return (void *)0;
- if (flags & CL_SORTED) {
- low = 0U;
- high = nodes;
- while (low < high) {
- mid = low +
- ((high - low) >> 1);
- if ((*cmP)(K,linkS[(first+mid)
- %limit]) <= 0)
- high = mid;
- else
- low = mid + 1;
- }
- if (high < nodes)
- if (!(*cmP)(K,D=linkS[(first+
- high)%limit])) {
- curNode = high;
- return D;
- }
- }
- else { /* linear search! */
- while ((D = next()) != (void *)0)
- if (!(*cmP)(K,D))
- return D;
- }
- return (void *)0;
- }
-
- void * cl::findNext(const void * K)
- {
-
- /*
- For sorted cls you must first call
- findFirst() to insure consistent results!
- */
-
- void * D;
-
- /*
- The current node is left undefined if
- anything fails, otherwise it is set to the
- newly found node.
- */
-
- if (!cmP)
- cmP = DcmP(voidCmP0);
- if (!linkS || !K || !cmP) {
- curNode = nodes;
- return (void *)0;
- }
- while ((D = next()) != (void *)0)
- if (!(*cmP)(K,D))
- return D;
- else if (flags & CL_SORTED) {
- curNode = nodes;
- break; /* Look no further! */
- }
- return (void *)0;
- }
-
- void * cl::findLast(const void * K)
- {
- unsigned low, mid, high;
- void * D;
-
- /*
- The current node is left undefined if
- anything fails, otherwise it is set to the
- newly found node.
- */
-
- curNode = nodes;
- if (!cmP) if ((cmP = DcmP(voidCmP0))
- == voidCmP0) return (void *)0;
- if (!linkS || !K || !nodes)
- return (void *)0;
- if (flags & CL_SORTED) {
- low = 0U;
- high = nodes;
- while (low < high) {
- mid = low +
- ((high - low) >> 1);
- if ((*cmP)(K,linkS[(first+mid)
- %limit]) < 0)
- high = mid;
- else
- low = mid + 1;
- }
- if (high < nodes)
- if (!(*cmP)(K,D=linkS[(first+
- high)%limit])) {
- curNode = high;
- return D;
- }
- }
- else { /* linear search! */
- while ((D = prev()) != (void *)0)
- if (!(*cmP)(K,D))
- return D;
- }
- return (void *)0;
- }
-
- void * cl::findPrev(const void * K)
- {
-
- /*
- For sorted cls you must first call
- findLast() to insure consistent results!
- */
-
- void * D;
-
- /*
- The current node is left undefined if
- anything fails, otherwise it is set to the
- newly found node.
- */
-
- if (!cmP)
- cmP = DcmP(voidCmP0);
- if (!linkS || !K || !cmP) {
- curNode = nodes;
- return (void *)0;
- }
- while ((D = prev()) != (void *)0)
- if (!(*cmP)(K,D))
- return D;
- else if (flags & CL_SORTED) {
- curNode = nodes;
- break; /* Look no further! */
- }
- return (void *)0;
- }
-
- unsigned cl::findAll(const void * K)
- {
- unsigned count = 0U;
-
- /* The current node is left undefined. */
-
- if (findFirst(K))
- do {
- count++;
- } while (findNext(K));
- return count;
- }
-
-
-
- struct GenericFnCRecord {
- GenericFnC fnC;
- unsigned id;
- GenericFnCRecord(GenericFnC fnC, unsigned id)
- { this->fnC = fnC; this->id = id; }
- ~GenericFnCRecord() {}
- };
-
- typedef struct GenericFnCRecord * GenericFnCR;
- #define GenericFnCR0 ((GenericFnCR)0)
-
- int FunctionRegistry::regFnC(GenericFnC fnC,
- unsigned id)
- {
- unsigned i;
-
- if (!fnC && !id) // NULL's id is 0
- return 1;
- if ((!fnC && id) || (fnC && !id))
- return 0;
- for (i = 0U; i < Nodes(); i++)
- if (((GenericFnCR)atGet(i))->id
- == id)
- break;
- if (i < Nodes())
- return 0;
- GenericFnCR R = new GenericFnCRecord(fnC,id);
- if (!R)
- return 0;
- else if (!insQ((void *)R)) {
- delete R;
- return 0;
- }
- return 1;
- }
-
- unsigned FunctionRegistry::fnC_2_ID(GenericFnC fnC)
- {
- GenericFnCR R;
- unsigned i;
-
- if (!fnC)
- return 0U;
- for (i = 0U; (R = (GenericFnCR) atGet(i))
- != GenericFnCR0; i++)
- if (R->fnC == fnC)
- return R->id;
- return 0U;
- }
-
- GenericFnC FunctionRegistry::ID_2_fnC(unsigned id)
- {
- GenericFnCR R;
- unsigned i;
-
- if (!id)
- return GenericFnC0;
- for (i = 0U; (R = (GenericFnCR) atGet(i))
- != GenericFnCR0; i++)
- if (R->id == id)
- return R->fnC;
- return GenericFnC0;
- }
-
- FunctionRegistry fnCv;
-